﻿using System;
using System.ComponentModel;
using MugenMvvmToolkit.Annotations;
using MugenMvvmToolkit.Attributes;
#if TASKSUPPORT
using System.Threading.Tasks;
#else
using MugenMvvmToolkit.Infrastructure;
using MugenMvvmToolkit.Interfaces;
#endif
using MugenMvvmToolkit.Interfaces.ViewModels;
using MugenMvvmToolkit.Interfaces.Views;
using MugenMvvmToolkit.Models;

namespace MugenMvvmToolkit.ViewModels
{
    /// <summary>
    ///     Represents the base class for child window view-models.
    /// </summary>
    [BaseViewModel(Priority = 1)]
    public abstract class ChildWindowViewModel : WindowViewModelBase<IChildWindowView>, IWindowViewModel
    {
        #region Constructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="ChildWindowViewModel" /> class.
        /// </summary>
        protected ChildWindowViewModel()
        {
        }

        #endregion

        #region Methods

        private void DialogViewOnClosing(object sender, CancelEventArgs cancelEventArgs)
        {
            OnViewClosing(sender, cancelEventArgs);
        }

        #endregion

        #region Overrides of DialogViewModelBase<IChildWindowView>

        /// <summary>
        ///     Configures a view model before show dialog. If you create custom dialog-view model you must call this method before show the dialog.
        /// </summary>
        /// <param name="onClosed">The specified callback which will execute after close current dialog.</param>
        /// <param name="viewNameBinding">The specified name of view binding, if any.</param>
        protected sealed override void ConfigureBeforeShow(ResultCallback<bool> onClosed = null, string viewNameBinding = null)
        {
            base.ConfigureBeforeShow(onClosed, viewNameBinding);
        }

        /// <summary>
        ///     Occurred on closing dialog-view.
        /// </summary>
        protected override sealed void OnViewClosing(object sender, CancelEventArgs e)
        {
            base.OnViewClosing(sender, e);
        }

        /// <summary>
        ///     Initializes the specified dialog view.
        /// </summary>
        /// <param name="windowView">The specified window-view to initialize.</param>
        protected override sealed void InitializeView(IChildWindowView windowView)
        {
            windowView.Closing += DialogViewOnClosing;
        }

        /// <summary>
        ///     Clears the specified dialog view.
        /// </summary>
        /// <param name="windowView">The specified window-view to dispose.</param>
        protected override sealed void CleanupView(IChildWindowView windowView)
        {
            windowView.Closing -= DialogViewOnClosing;
        }

        #endregion

        #region Implementation of IWindowViewModel

#if TASKSUPPORT
        /// <summary>
        ///     Shows the current <see cref="IWindowViewModel" /> as a window.
        /// </summary>
        /// <param name="viewNameBinding">The specified name of view binding, if any.</param>
        public Task<bool> ShowAsync(string viewNameBinding = null)
        {
            var result = new TaskCompletionSource<bool>();
            ThreadManager.InvokeInUi(() =>
            {
                ConfigureBeforeShow((exception, b) =>
                {
                    if (exception != null)
                    {
                        result.SetException(exception);
                        return;
                    }
                    result.SetResult(b);
                }, viewNameBinding);
                DialogView.Show();
            });
            return result.Task;
        }
#else
        /// <summary>
        ///     Shows the current <see cref="IWindowViewModel" /> as a window.
        /// </summary>
        /// <param name="viewNameBinding">The specified name of view binding, if any.</param>
        public IOperationResult<bool> ShowAsync(string viewNameBinding = null)
        {
            var result = new ManualOperationResult<bool>();
            ThreadManager.InvokeInUi(() =>
            {
                ConfigureBeforeShow((exception, b) =>
                {
                    if (exception != null)
                    {
                        result.SetException(exception);
                        return;
                    }
                    result.SetResult(b);
                }, viewNameBinding);
                DialogView.Show();
            });
            return result;
        }
#endif
        #endregion
    }
}